```plaintext
=======================================================================
WELCOME BACK TO REGULAR EXPRESSIONS WITH PYTHON'S RE MODULE: LESSON 3
=======================================================================

Hello again! Ready to dive deeper into the world of Regular Expressions with Python's `re` module? In this lesson, we'll explore more advanced topics, including quantifiers and lookarounds, to further enhance your pattern-matching skills.

As before, please open your terminal and type `ipython` to start the interactive Python shell. Import the `re` module using:

```python
import re
```

=======================================================================
CONCEPT 1: SPECIFIC REPETITIONS WITH {}
=======================================================================

Curly braces `{}` allow you to specify the exact number of times an element should repeat. You can set both a minimum and maximum repetition count.

**Example:** Let's find sequences of 3 to 5 digits.

```python
match = re.search(r'\d{3,5}', 'Sample ID: 12345')
```

In the string, '12345' has 5 digits which matches our condition. Try it yourself.

=======================================================================
EXERCISE 1:
=======================================================================

Write a pattern to match sequences of exactly four letters using `{} `in the string 'Word play lead grain'.

```python
# Your code here
```

**Expected Outcome:** Identify words like 'play' and 'lead'.

=======================================================================
CONCEPT 2: ALTERNATION WITH |
=======================================================================

The pipe `|` character in regex acts like a logical OR, allowing you to choose between different sub-patterns.

**Example:** Let's match the words 'cat' or 'dog'.

```python
match = re.search(r'cat|dog', 'I have a dog.')
```

Try it to see which word is matched first.

=======================================================================
EXERCISE 2:
=======================================================================

Use alternation to match either 'apple' or 'banana' in the string 'I like apple and banana pie'.

```python
# Your code here
```

**Expected Outcome:** Your regex should match the first appearance of 'apple' or 'banana'.

=======================================================================
CONCEPT 3: LOOKAHEADS
=======================================================================

Lookaheads (?=...) allow you to assert if a pattern is followed by another pattern, without including it in the match.

**Example:** Match 'book' only if it is followed by 'case'.

```python
match = re.search(r'book(?=case)', 'bookcase on the shelf')
```

Give it a try and see how it works.

=======================================================================
EXERCISE 3:
=======================================================================

Create a lookahead to find the word 'red' when it is followed by 'apple'.

```python
# Your code here
```

**Expected Outcome:** 'red' should only be matched when it's right before 'apple'.

=======================================================================
CONCEPT 4: LOOKBEHINDS
=======================================================================

Lookbehinds (?<=...) allow you to assert that a pattern is preceded by another pattern. Like lookaheads, they don't include the preceding pattern in the match.

**Example:** Capture 'ing' if it is preceded by 'read'.

```python
match = re.search(r'(?<=read)ing', 'reading is fun')
```

Test this in your shell.

=======================================================================
EXERCISE 4:
=======================================================================

Write a regex to find 'stopping' only if it is preceded by 'bus'.

```python
# Your code here
```

**Expected Outcome:** The word 'stopping' should only be matched if preceded by 'bus'.

=======================================================================
CHALLENGE:
=======================================================================

Combine all of today's concepts to extract words of exactly six letters, preceded by 'the', and followed by 'fox' or 'dog' from the sentence: "The quick brown fox jumps over the lazy dog."

```python
# Your code here
```

**Success Criteria:** Your regular expression should extract 'quick' and 'brown'.

=======================================================================
FURTHER EXPLORATION:
=======================================================================

- Experiment with greedy vs lazy quantifiers using +? and *?.
- Learn about non-capturing groups with (?...) for patterns you don't need to save.
- Explore negative lookahead and lookbehinds.
- Try `re.sub()` to perform substitution based on patterns you've learned.

You've got a solid grasp of regex now. Each lesson builds on the last, so keep practicing and experimenting. I'm looking forward to the next steps in your regex journey!

=======================================================================
```